﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Reflection;


namespace SharpHsql.Data.Client {
    class SharpHsqlProviderFactory : DbProviderFactory,IServiceProvider {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Factory class is immutable.")]
        public static readonly SharpHsqlProviderFactory Instance = new SharpHsqlProviderFactory();

        /// <summary>
        /// Specifies whether the specific <see cref="T:System.Data.Common.DbProviderFactory"/> supports the <see cref="T:System.Data.Common.DbDataSourceEnumerator"/> class.
        /// </summary>
        /// <value></value>
        /// <returns>true if the instance of the <see cref="T:System.Data.Common.DbProviderFactory"/> supports the <see cref="T:System.Data.Common.DbDataSourceEnumerator"/> class; otherwise false.
        /// </returns>
        public override bool CanCreateDataSourceEnumerator {
            get { return false; }
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbCommand"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbCommand"/>.
        /// </returns>
        public override DbCommand CreateCommand() {
            return new SharpHsqlCommand();
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbCommandBuilder"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbCommandBuilder"/>.
        /// </returns>
        public override DbCommandBuilder CreateCommandBuilder() {
            return new SharpHsqlCommandBuilder();
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbConnection"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbConnection"/>.
        /// </returns>
        public override DbConnection CreateConnection() {
            return new SharpHsqlConnection();
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbConnectionStringBuilder"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbConnectionStringBuilder"/>.
        /// </returns>
        public override DbConnectionStringBuilder CreateConnectionStringBuilder() {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbDataAdapter"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbDataAdapter"/>.
        /// </returns>
        public override DbDataAdapter CreateDataAdapter() {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbDataSourceEnumerator"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbDataSourceEnumerator"/>.
        /// </returns>
        public override DbDataSourceEnumerator CreateDataSourceEnumerator() {
            return System.Data.Sql.SqlDataSourceEnumerator.Instance;
        }

        /// <summary>
        /// Returns a new instance of the provider's class that implements the <see cref="T:System.Data.Common.DbParameter"/> class.
        /// </summary>
        /// <returns>
        /// A new instance of <see cref="T:System.Data.Common.DbParameter"/>.
        /// </returns>
        public override DbParameter CreateParameter() {
            return new SharpHsqlParameter();
        }

        private FieldInfo sqlDbProviderServicesInstance;

        private FieldInfo DbProviderServicesInstance {
            get {
                if (sqlDbProviderServicesInstance == null) {
                    string fullName = Assembly.GetExecutingAssembly().FullName;
                    fullName = fullName.Replace("SharpHsql.Data.Client", "SharpHsql.Data.Entity");
                    fullName = String.Format("SharpHsql.Data.Entity.SharpHsqlProviderServices, {0}", fullName);

                    Type providerServicesType = Type.GetType(fullName, false);
                    sqlDbProviderServicesInstance = providerServicesType.GetField("Instance",
                        BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
                }
                return sqlDbProviderServicesInstance;
            }
        }

        object IServiceProvider.GetService(Type serviceType) {
            // DbProviderServices is the only service we offer up right now
            //if (serviceType.GetInterface( != DbServicesType) return null;

            if (DbProviderServicesInstance == null) return null;
                return DbProviderServicesInstance.GetValue(null);
        }
    }
}
